home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / DIKUMUD.ZIP / MOBACT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  20.2 KB  |  956 lines

  1. /*
  2.   SillyMUD Distribution V1.1b             (c) 1993 SillyMUD Developement
  3.  
  4.   See license.doc for distribution terms.   SillyMUD is based on DIKUMUD
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9.  
  10. #include "protos.h"
  11.  
  12. extern struct char_data *character_list;
  13. extern struct index_data *mob_index;
  14. #if HASH
  15. extern struct hash_header room_db;
  16. #else
  17. extern struct room_data *room_db;
  18. #endif
  19. extern struct str_app_type str_app[];
  20. extern struct index_data *mob_index;
  21.  
  22. int top_of_comp = 0;
  23.  
  24. void mobile_guardian(struct char_data *ch)
  25. {
  26.   struct char_data *targ;
  27.   int i, found=FALSE;
  28.   
  29.   if (ch->in_room > -1) {
  30.     if ((!ch->master) || (!IS_AFFECTED(ch, AFF_CHARM)))
  31.       return;
  32.     if (ch->master->specials.fighting) { /**/
  33.       for(i=0;i<10&&!found;i++) {
  34.     targ = FindAnAttacker(ch->master);
  35.     if (targ)
  36.       found=TRUE;
  37.       }
  38.       
  39.       if (!found) return;
  40.       
  41.       if (!SameRace(targ, ch)) {
  42.     if (IsHumanoid(ch)) {
  43.       act("$n screams 'I must protect my master!'", 
  44.           FALSE, ch, 0, 0, TO_ROOM);
  45.     } else {
  46.       act("$n growls angrily!", 
  47.           FALSE, ch, 0, 0, TO_ROOM);
  48.     }
  49.     if (CAN_SEE(ch, targ))
  50.       hit(ch, targ,0);      
  51.       }
  52.     }
  53.   }
  54. }
  55.  
  56. void mobile_wander(struct char_data *ch)
  57. {
  58.   int    door, or;
  59.   struct room_direction_data    *exitp;
  60.   struct room_data    *rp;
  61.   char buf[100];
  62.  
  63.   if (GET_POS(ch) != POSITION_STANDING)
  64.     return;
  65.  
  66.   or = ch->in_room;
  67.  
  68.   while(1) {
  69.  
  70.     door = number(0,8);
  71.     if (door > 5) return;
  72.  
  73.     if (door = ch->specials.last_direction)
  74.       continue;
  75.  
  76.     exitp = EXIT(ch, door);
  77.  
  78.     if (!exit_ok(exitp, &rp)) continue;
  79.  
  80.     if (IS_SET(rp->room_flags, NO_MOB|DEATH))
  81.       continue;
  82.  
  83.     if (GET_RACE(ch) == RACE_FISH) {
  84.       rp = real_roomp(EXIT(ch, door)->to_room);
  85.  
  86.       if (rp->sector_type == SECT_UNDERWATER ||
  87.       rp->sector_type == SECT_WATER_NOSWIM ||
  88.       rp->sector_type == SECT_WATER_SWIM) {
  89.     /* then it is ok for the fish to wander there */
  90.       } else {
  91.     return;
  92.       }
  93.     }
  94.  
  95.     if (IsHumanoid(ch) ? CAN_GO_HUMAN(ch, door) : CAN_GO(ch, door)) {
  96.       if (!IS_SET(ch->specials.act, ACT_STAY_ZONE) ||
  97.       (rp->zone == real_roomp(ch->in_room)->zone)) {
  98.     ch->specials.last_direction = door;
  99.     go_direction(ch, door);
  100.     if (ch->in_room == 0) {
  101.       if (or != 0) {
  102.         sprintf(buf, "%s just entered void from %d", GET_NAME(ch), or);
  103.         log_sev(buf,5);
  104.       }
  105.     }
  106.     return;
  107.       }
  108.     }
  109.   }
  110. }
  111.  
  112. void MobHunt(struct char_data *ch)
  113. {
  114.   int res, k;
  115.   
  116. #if NOTRACK     
  117.   return;    /* too much CPU useage for some machines.  */
  118. #endif
  119.   
  120.   if (ch->persist <= 0) {
  121.     res = choose_exit_in_zone(ch->in_room, ch->old_room, 2000);
  122.     if (res > -1) {
  123.       go_direction(ch, res);
  124.     } else {
  125.       if (ch->specials.hunting) {
  126.     if (ch->specials.hunting->in_room == ch->in_room) {
  127.       if (Hates(ch, ch->specials.hunting) && 
  128.           (!IS_AFFECTED(ch->specials.hunting, AFF_HIDE))) {
  129.         if (check_peaceful(ch, "You'd love to tear your quarry to bits, but you just CAN'T\n\r")) {
  130.           act("$n fumes at $N", TRUE, ch, 0,
  131.           ch->specials.hunting, TO_ROOM); 
  132.         } else {
  133.           if (IsHumanoid(ch)) {
  134.         act("$n screams 'Time to die, $N'", 
  135.             TRUE, ch, 0, ch->specials.hunting, TO_ROOM); 
  136.           } else if (IsAnimal(ch)) {
  137.         act("$n growls.", TRUE, ch, 0, 0, TO_ROOM);
  138.           }
  139.           MobHit(ch,ch->specials.hunting,0);
  140.           return;
  141.         }
  142.       }
  143.     }
  144.       }
  145.       REMOVE_BIT(ch->specials.act, ACT_HUNTING);
  146.       ch->specials.hunting = 0;
  147.       ch->hunt_dist = 0;
  148.     }
  149.   } else if (ch->specials.hunting) {
  150.     if (ch->hunt_dist <= 50) 
  151.       ch->hunt_dist = 100;
  152.     for (k=1;k<=1 && ch->specials.hunting; k++) {
  153.       ch->persist -= 1;
  154.       res = dir_track(ch, ch->specials.hunting);
  155.       if (res!= -1) {
  156.     go_direction(ch, res);
  157.       } else {
  158.     ch->persist = 0;
  159.     ch->specials.hunting = 0;
  160.     ch->hunt_dist = 0;
  161.       }
  162.     }
  163.   } else {
  164.     ch->persist = 0;
  165.   }           
  166. }
  167.  
  168. void MobScavenge(struct char_data *ch)
  169. {
  170.   struct obj_data *best_obj=0, *obj=0;
  171.   int max, cc=0;
  172.   char buf[512];
  173.   
  174.   if ((real_roomp(ch->in_room))->contents && number(0,4)) {
  175.     for (max = 1,best_obj = 0,obj = (real_roomp(ch->in_room))->contents;
  176.      obj; obj = obj->next_content) {
  177.       if (IS_CORPSE(obj)) {
  178.     cc++;
  179.     if (obj->contains) {
  180.       if (IsHumanoid(ch) && !number(0,4)) {
  181.         sprintf(buf, " all %d.corpse", cc);
  182.         do_get(ch, buf, 0);
  183.         return;
  184.       }
  185.     }
  186.       }
  187.       if (CAN_GET_OBJ(ch, obj)) {
  188.     if (obj->obj_flags.cost > max) {
  189.       best_obj = obj;
  190.       max = obj->obj_flags.cost;
  191.     }
  192.       }
  193.     } /* for */
  194.     
  195.     if (best_obj) {
  196.       if (!CheckForAnyTrap(ch, best_obj)) {
  197.     obj_from_room(best_obj);
  198.     obj_to_char(best_obj, ch);
  199.     act("$n gets $p.",FALSE,ch,best_obj,0,TO_ROOM);
  200.       }
  201.     }
  202.   } else {
  203.     if (IsHumanoid(ch) && real_roomp(ch->in_room)->contents) {
  204.       if (!number(0,4)) 
  205.     do_get(ch, "all", 0);
  206.     }
  207.   }
  208.  
  209. #if 0
  210.   if (number(0,3)) {
  211.     for( obj=ch->carrying;obj;obj=obj->next) {
  212.       if (IS_OBJ_STAT(obj, ITEM_NODROP)) {
  213.     do_junk(ch, obj->name, 0);
  214.       }
  215.     }
  216.   }
  217. #endif
  218.  
  219.   if (!number(0,3)) {
  220.     if (IsHumanoid(ch) && ch->carrying) {
  221.       sprintf(buf, "all");
  222.       do_wear(ch, buf, 0);
  223.     }
  224.   }
  225. }
  226.  
  227.  
  228. void check_mobile_activity(int pulse)
  229. {
  230.   register struct char_data *ch; 
  231.   int tick, tm;
  232.   
  233.   tm = pulse % PULSE_MOBILE;    /* this is dependent on P_M = 3*P_T */
  234.   
  235.   if (tm == 0) {
  236.     tick = 0;
  237.   } else if (tm == PULSE_TELEPORT) {
  238.     tick = 1;
  239.   } else if (tm == PULSE_TELEPORT*2) {
  240.     tick = 2;
  241.   }
  242.   
  243.   for (ch = character_list; ch; ch = ch->next) {
  244.     if (IS_MOB(ch)) {
  245.       if (ch->specials.tick == tick) {
  246.     mobile_activity(ch);
  247.       }
  248.     }
  249.   }
  250. }
  251.  
  252. void mobile_activity(struct char_data *ch)
  253. {
  254.   struct char_data *tmp_ch;
  255.  
  256.   int k;
  257.   char buf[80];
  258.   extern int no_specials;
  259.   
  260.   void do_move(struct char_data *ch, char *argument, int cmd);
  261.   void do_get(struct char_data *ch, char *argument, int cmd);
  262.   
  263.   /* Examine call for special procedure */
  264.   
  265.   /* some status checking for errors */
  266. #if HASH
  267.   if ((ch->in_room < 0) || !hash_find(&room_db,ch->in_room)) {
  268. #else
  269.   if ((ch->in_room < 0) || !room_find(&room_db,ch->in_room)) {
  270. #endif
  271.       log("Char not in correct room.  moving to 50 ");
  272.       log(GET_NAME(ch));
  273.       assert(ch->in_room >= 0);  /* if they are in a - room, assume an error */
  274.       char_from_room(ch);
  275.       char_to_room(ch, 50);
  276.   }
  277.  
  278.   /* Execute a script if there is one */
  279.  
  280.   if(IS_SET(ch->specials.act, ACT_SCRIPT) && !IS_PC(ch))
  281.     DoScript(ch);
  282.  
  283.     
  284.   if (((IS_SET(ch->specials.act, ACT_SPEC) || mob_index[ch->nr].func)) && !no_specials) {
  285.     if (!mob_index[ch->nr].func) {
  286.       char buf[180];
  287.       sprintf(buf, "Attempting to call a non-existing mob func on %s", GET_NAME(ch));
  288.       log(buf);
  289.       REMOVE_BIT(ch->specials.act, ACT_SPEC);
  290.     } else {
  291.  
  292.       if ((*mob_index[ch->nr].func)    (ch, 0, "", ch, PULSE_TICK))
  293.     return;
  294.     }
  295.   }
  296.   
  297.   
  298.   /* check to see if the monster is possessed */
  299.   
  300.   if (AWAKE(ch) && (!ch->specials.fighting) && (!ch->desc) &&
  301.       (!IS_SET(ch->specials.act, ACT_POLYSELF))) {
  302.     
  303.     if (!AssistFriend(ch)) {
  304.       return;
  305.     }
  306.     
  307.     if (IS_SET(ch->specials.act, ACT_SCAVENGER)) {
  308.       MobScavenge(ch);
  309.     } /* Scavenger */
  310.     
  311.     
  312.     if (IS_SET(ch->specials.act, ACT_HUNTING)) {
  313.       MobHunt(ch);
  314.     } else if ((!IS_SET(ch->specials.act, ACT_SENTINEL)))
  315.       mobile_wander(ch);
  316.     
  317.     if (GET_HIT(ch) > (GET_MAX_HIT(ch)/2)) {
  318.       if (IS_SET(ch->specials.act, ACT_HATEFUL)) {
  319.     tmp_ch = FindAHatee(ch);
  320.     if (tmp_ch) {
  321.       if (check_peaceful(ch, "You ask your mortal enemy to step outside to settle matters.\n\r")) {
  322.         act("$n growls '$N, would you care to step outside where we can settle this?'", TRUE, ch, 0, tmp_ch, TO_ROOM);
  323.       } else {
  324.         if (IsHumanoid(ch)) {
  325.           act("$n screams 'I'm gonna kill you!'", 
  326.           TRUE, ch, 0, 0, TO_ROOM); 
  327.         } else if (IsAnimal(ch)) {
  328.           act("$n growls", TRUE, ch, 0, 0, TO_ROOM);
  329.         }
  330.         MobHit(ch,tmp_ch,0);
  331.       }
  332.       if (Hates(ch, tmp_ch) && Fears(ch, tmp_ch)) {
  333.         RemHated(ch, tmp_ch);
  334.         RemFeared(ch, tmp_ch);
  335.       }
  336.     }
  337.       }
  338.       if (!ch->specials.fighting) {
  339.     if (IS_SET(ch->specials.act, ACT_AFRAID)) {
  340.       if ((tmp_ch = FindAFearee(ch))!= NULL) {
  341.         do_flee(ch, "", 0);
  342.       }
  343.     }
  344.       }
  345.     } else {
  346.       if (IS_SET(ch->specials.act, ACT_AFRAID)) {
  347.     if ((tmp_ch = FindAFearee(ch))!= NULL) {
  348.       do_flee(ch, "", 0);
  349.     } else {
  350.       if (IS_SET(ch->specials.act, ACT_HATEFUL)) {
  351.         tmp_ch = FindAHatee(ch);
  352.         if (tmp_ch) {
  353.           if (check_peaceful(ch, "You ask your mortal enemy to step outside to settle matters.\n\r")) {
  354.         act("$n growls '$N, would you care to step outside where we can settle this?'", TRUE, ch, 0, tmp_ch, TO_ROOM);
  355.           } else {
  356.         if (IsHumanoid(ch)) {
  357.           act("$n screams 'I'm gonna get you!'", 
  358.               TRUE, ch, 0, 0, TO_ROOM); 
  359.         } else if (IsAnimal(ch)) {
  360.           act("$n growls", TRUE, ch, 0, 0, TO_ROOM);
  361.         }
  362.         hit(ch,tmp_ch,0);
  363.           }
  364.           if (Hates(ch, tmp_ch) && Fears(ch, tmp_ch)) {
  365.         RemHated(ch, tmp_ch);
  366.         RemFeared(ch, tmp_ch);
  367.           }
  368.         }
  369.       }             
  370.     }
  371.       }
  372.     }
  373.  
  374.     if (IS_SET(ch->specials.act,ACT_AGGRESSIVE)) {
  375.       for (k=0;k<=5;k++) {
  376.     tmp_ch = FindVictim(ch);
  377.     if (tmp_ch) {
  378.       if (check_peaceful(ch, "You can't seem to exercise your violent tendencies.\n\r")) {
  379.         act("$n growls impotently", TRUE, ch, 0, 0, TO_ROOM);
  380.         return;
  381.       }
  382.       MobHit(ch, tmp_ch, 0);
  383.       k = 10;
  384.     }
  385.       }
  386.     }
  387.     if (IS_SET(ch->specials.act, ACT_META_AGG)) {
  388.       for (k=0;k<=5;k++) {
  389.     tmp_ch = FindMetaVictim(ch);
  390.     if (tmp_ch) {
  391.       if (check_peaceful(ch, "You can't seem to exercise your violent tendencies.\n\r")) {
  392.         act("$n growls impotently", TRUE, ch, 0, 0, TO_ROOM);
  393.         return;
  394.       }
  395.       MobHit(ch, tmp_ch, 0);
  396.       k = 10;
  397.     }
  398.       }
  399.       
  400.     }
  401.     if (IS_SET(ch->specials.act, ACT_GUARDIAN)) {
  402.       mobile_guardian(ch);
  403.     }    
  404.  
  405.   } /* If AWAKE(ch)   */
  406.   if (!IS_PC(ch) && ch->specials.fighting) {
  407.     if (IS_AFFECTED(ch->specials.fighting, AFF_FIRESHIELD)) {
  408.       struct char_data *vict;
  409.       vict = FindVictim(ch);
  410.       /* switch to a new target */
  411.       if (vict && vict != ch->specials.fighting) {
  412.     stop_fighting(ch);
  413.     set_fighting(ch, vict);
  414.       }
  415.     }
  416.   }
  417. }
  418.   
  419.   
  420.   
  421. int SameRace( struct char_data *ch1, struct char_data *ch2)
  422. {    
  423.     if ((!ch1) || (!ch2))
  424.       return(FALSE);
  425.     
  426.     if (ch1 == ch2)
  427.       return(TRUE);
  428.     
  429.     if (in_group(ch1,ch2))
  430.       return(TRUE);
  431.     
  432.     if (GET_RACE(ch1) == GET_RACE(ch2)) {
  433.       return(TRUE);
  434.     }
  435.     
  436.     return(FALSE);
  437. }
  438.   
  439. int AssistFriend( struct char_data *ch)
  440. {
  441.   struct char_data *damsel, *targ, *tmp_ch, *next;
  442.   int t, found;
  443.   char buf[256];
  444.   
  445.   damsel = 0;
  446.   targ = 0;
  447.   
  448.   if (check_peaceful(ch, ""))
  449.     return;
  450. #if 0
  451.   assert(ch->in_room >= 0); 
  452. #else
  453.   if (ch->in_room < 0) {
  454.     sprintf(buf, "Mob %sin negative room", ch->player.name);
  455.     log(buf);
  456.     ch->in_room = 0;
  457.     extract_char(ch);
  458.     return(0);
  459.   }
  460. #endif
  461.   if (ch->in_room == 0) 
  462.     return(0);
  463.   
  464.   /*
  465.     find the people who are fighting
  466.     */
  467.   
  468.   for (tmp_ch=(real_roomp(ch->in_room))->people;tmp_ch;
  469.        tmp_ch=next) {
  470.     next = tmp_ch->next_in_room;
  471.     if (CAN_SEE(ch,tmp_ch)) {
  472.       if (!IS_SET(ch->specials.act, ACT_WIMPY)) {
  473.     if (MobFriend(ch, tmp_ch)) {
  474.       if (tmp_ch->specials.fighting)
  475.         damsel = tmp_ch;
  476.     }
  477.       }
  478.     }
  479.   }
  480.   
  481.   if (damsel) {
  482.     /*
  483.       check if the people in the room are fighting.
  484.       */
  485.     found = FALSE;
  486.     for (t=1; t<=8 && !found;t++) {
  487.       targ = FindAnAttacker(damsel);
  488.       if (targ) {
  489.     if (targ->specials.fighting)
  490.         found = TRUE;
  491.       }
  492.     }
  493.     if (targ) {
  494.       if (targ->in_room == ch->in_room) {
  495.     if (!IS_AFFECTED(ch, AFF_CHARM) ||
  496.         ch->master != targ) {
  497.       hit(ch,targ,0);
  498.     }
  499.       }
  500.     }
  501.   }
  502.   return(1);
  503. }
  504.   
  505. FindABetterWeapon(struct char_data *mob)
  506. {
  507.   struct obj_data *o, *best;
  508.   /*
  509.     pick up and wield weapons
  510.     Similar code for armor, etc.
  511.     */
  512.   
  513.   /* check whether this mob can wield */
  514.   if (!HasHands(mob)) return(FALSE);
  515.   
  516.   if (!real_roomp(mob->in_room)) return(FALSE);
  517.   
  518.   /* check room */
  519.   best = 0;
  520.   for (o = real_roomp(mob->in_room)->contents; o; o = o->next_content) {
  521.     if (best && IS_WEAPON(o)) {
  522.       if (GetDamage(o,mob) > GetDamage(best,mob)) {
  523.     best = o;
  524.       }
  525.     } else {
  526.       if (IS_WEAPON(o)) {
  527.     best = o;
  528.       }
  529.     }
  530.   }
  531.   /* check inv */
  532.   for (o = mob->carrying; o; o=o->next_content) {
  533.     if (best && IS_WEAPON(o)) {
  534.       if (GetDamage(o,mob) > GetDamage(best,mob)) {
  535.     best = o;
  536.       }
  537.     } else {
  538.       if (IS_WEAPON(o)) {
  539.     best = o;
  540.       }
  541.     }
  542.   }
  543.   
  544.   if (mob->equipment[WIELD]) {
  545.     if (best) {
  546.        if (GetDamage(mob->equipment[WIELD],mob) >= GetDamage(best,mob)) {
  547.           best = mob->equipment[WIELD];
  548.        }
  549.     } else {
  550.       best = mob->equipment[WIELD];
  551.     }
  552.   }
  553.  
  554.   if (best) {
  555.      if (GetHandDamage(mob) > GetDamage(best, mob)) {
  556.         best = 0;
  557.      }
  558.   } else {
  559.     return(FALSE);  /* nothing to choose from */
  560.   }
  561.  
  562.   if (best) {
  563.       /*
  564.     out with the old, in with the new
  565.       */
  566.       if (best->carried_by == mob) {
  567.      if (mob->equipment[WIELD]) {
  568.             do_remove(mob, mob->equipment[WIELD]->name, 0);
  569.      }
  570.          do_wield(mob, best->name, 0);
  571.       } else if (best->equipped_by == mob) {
  572.     /* do nothing */
  573.     return(TRUE);
  574.       } else {
  575.          do_get(mob, best->name, 0);
  576.       }      
  577.   } else {
  578.     if (mob->equipment[WIELD]) {
  579.       do_remove(mob, mob->equipment[WIELD]->name, 0);
  580.     }
  581.   }
  582. }
  583.       
  584. int GetDamage(struct obj_data *w, struct char_data *ch) 
  585. {
  586.   float ave;
  587.   int iave;
  588.   /*
  589.     return the average damage of the weapon, with plusses.
  590.   */
  591.  
  592.   ave = w->obj_flags.value[2]/2.0 + 0.5;
  593.     
  594.   ave *=w->obj_flags.value[1];
  595.   
  596.   ave += GetDamBonus(w);
  597.   /*
  598.     check for immunity:
  599.     */
  600.   iave = ave;
  601.   if (ch->specials.fighting) {
  602.     iave = PreProcDam(ch->specials.fighting, ITEM_TYPE(w), iave);
  603.     iave = WeaponCheck(ch, ch->specials.fighting, ITEM_TYPE(w), iave);
  604.   }
  605.   return(iave);
  606. }
  607.       
  608. int GetDamBonus(struct obj_data *w)
  609. {
  610.    int j, tot=0;
  611.  
  612.     /* return the damage bonus from a weapon */
  613.    for(j=0; j<MAX_OBJ_AFFECT; j++) {
  614.       if (w->affected[j].location == APPLY_DAMROLL || 
  615.       w->affected[j].location == APPLY_HITNDAM) {
  616.       tot += w->affected[j].modifier;    
  617.     }
  618.     }
  619.     return(tot);
  620. }
  621.           
  622. int GetHandDamage(struct char_data *ch) 
  623. {
  624.   float ave;
  625.   int num, size, iave;
  626.   /*
  627.     return the hand damage of the weapon, with plusses.
  628.     dam += dice(ch->specials.damnodice, ch->specials.damsizedice);
  629.  
  630.     */
  631.  
  632.   num  = ch->specials.damnodice;
  633.   size = ch->specials.damsizedice;
  634.   
  635.   ave = size/2.0 + 0.5;
  636.     
  637.   ave *= num;  
  638.  
  639.   /*
  640.     check for immunity:
  641.     */
  642.   iave = ave;
  643.   if (ch->specials.fighting) {
  644.     iave = PreProcDam(ch->specials.fighting, TYPE_HIT, iave);
  645.     iave = WeaponCheck(ch, ch->specials.fighting, TYPE_HIT, iave);
  646.   }
  647.   return(iave);
  648. }
  649.  
  650. /*
  651.   check to see if a mob is a friend
  652.  
  653. */
  654.  
  655.  
  656. int MobFriend( struct char_data *ch, struct char_data *f)
  657. {
  658.  
  659.    if (SameRace(ch, f)) {
  660.      if (IS_GOOD(ch)) {
  661.        if (IS_GOOD(f)) {
  662.           return(TRUE);
  663.     } else {
  664.       return(FALSE);
  665.     }
  666.      } else {
  667.        if (IS_NPC(f))
  668.           return(TRUE);
  669.      }
  670.    } else {
  671.      return(FALSE);
  672.    }
  673.  
  674. }
  675.  
  676. void PulseMobiles(int type)
  677. {
  678.  register struct char_data *ch;
  679.  
  680.  for(ch = character_list; ch; ch = ch->next)
  681.     if(IS_MOB(ch))
  682.       if(mob_index[ch->nr].func)
  683.         (*mob_index[ch->nr].func)(ch, 0, "", ch, type);
  684.  
  685. void DoScript(struct char_data *ch)
  686. {
  687.  int i, check = 0;
  688.  char buf[255], buf2[255], buf3[255], *s;
  689.  
  690.  strcpy(buf, script_data[ch->script].script[ch->commandp].line);
  691.  
  692.  if(buf[strlen(buf) - 1] == '\\') {
  693.     check = 1;
  694.     buf[strlen(buf) - 1] = '\0';
  695.  }
  696.  
  697.  strcpy(buf2, buf);
  698.  strtok(buf2, " ");
  699.  s = strtok(NULL, " ");
  700.  
  701.  
  702.  i = CommandSearch(buf2);
  703.  
  704.  if(i == -1) {
  705.     command_interpreter(ch, buf);
  706.     ch->commandp++;
  707.     return;
  708.   }
  709.  if(s)
  710.    (*comp[i].p)(s, ch);
  711.  else
  712.    (*comp[i].p)("\0", ch);
  713.  
  714.  if(*script_data[ch->script].script[ch->commandp].line == '_')
  715.    ch->commandp++;
  716.  
  717.  if(check)
  718.     DoScript(ch);
  719. }
  720.  
  721. int CommandSearch(char *arg)
  722. {
  723.  int i;
  724.  
  725.  for(i = 0; i < top_of_comp; i++)
  726.     if(!strcmp(comp[i].arg, arg))
  727.        return(i);
  728.  
  729.  return(-1);
  730. }
  731.  
  732. void CommandAssign(char *arg, void (*p))
  733. {
  734.  if(top_of_comp == 0)
  735.     comp = (struct script_com *)malloc(sizeof(struct script_com));
  736.  else
  737.     comp = (struct script_com *) realloc(comp, sizeof(struct script_com) * (top_of_comp + 1));
  738.  comp[top_of_comp].p = p;
  739.  comp[top_of_comp].arg = (char *) malloc(sizeof(char) * (strlen(arg) + 1));
  740.  strcpy(comp[top_of_comp].arg, arg);
  741.  top_of_comp++;
  742. }
  743.  
  744. void CommandSetup()
  745. {
  746.  CommandAssign("noop", noop);
  747.  CommandAssign("goto", sgoto);
  748.  CommandAssign("end", end2);
  749.  CommandAssign("act", do_act);
  750.  CommandAssign("jsr", do_jsr);
  751.  CommandAssign("jmp", do_jmp);
  752.  CommandAssign("rts", do_rts);
  753.  CommandAssign("stop", end2);
  754. }
  755.  
  756. void noop(char *arg, struct char_data *ch)
  757. {
  758.  int i;
  759.  
  760.  if(ch->waitp > 0) {
  761.     if(ch->waitp == 1) {
  762.        ch->waitp = 0;
  763.        ch->commandp++;
  764.        return;
  765.      }
  766.  
  767.     ch->waitp--;
  768.     return;
  769.   }
  770.  
  771.  if(*arg) {
  772.    i = atoi(arg);
  773.  
  774.    if(i <= 0) {
  775.      ch->commandp++;
  776.      return;
  777.    }
  778.  
  779.    ch->waitp = i - 1;
  780.    return;
  781.  }
  782.  ch->commandp++;
  783.  return; 
  784. }
  785.  
  786. void end2(char *arg, struct char_data *ch)
  787. {
  788.  ch->commandp = 0;
  789. }  
  790.  
  791. void sgoto(char *arg, struct char_data *ch)
  792. {
  793.    char *p, buf[255];
  794.    struct char_data *mob;
  795.    int dir, room;
  796.  
  797.    if(arg) {
  798.      if (*arg == '$') {  /* this is a creature name to follow */
  799.        arg++;
  800.        p = strtok(arg, " ");
  801.        if ((mob = get_char_vis(ch, p)) == NULL) {
  802.      fprintf(stderr, "%s couldn't find mob by name %s\n", 
  803.          script_data[ch->script].filename, p);
  804.      ch->commandp++;
  805.      return;
  806.        } else {
  807.      room = mob->in_room;
  808.        }
  809.      }else {
  810.        room = atoi(arg);
  811.      }
  812.    } else {
  813.      char buf3[150];
  814.      sprintf(buf, "Error in script %s, no destination for goto", 
  815.          script_data[ch->script].filename);
  816.      log(buf);
  817.      ch->commandp++;
  818.      return;
  819.    }
  820.    if (ch->in_room != room) {
  821.      dir = choose_exit_global(ch->in_room, room, MAX_ROOMS);
  822.      if (dir < 0) {
  823.        do_say(ch, "Woah!  How'd i get here??", 0);
  824.        do_emote(ch, "vanishes in a puff of smoke", 0);
  825.        char_from_room(ch);
  826.        char_to_room(ch, room);
  827.        do_emote(ch, "arrives with a Bamf!", 0);
  828.        ch->commandp++;
  829.        return;
  830.      }
  831.      go_direction(ch, dir);
  832.      if (ch->in_room == room)
  833.        ch->commandp++;
  834.      return;
  835.    }
  836.    ch->commandp++;
  837. }
  838.  
  839. void do_act(char *arg, struct char_data *ch)
  840. {
  841.    int bits;
  842.    if (arg) {
  843.      bits = atoi(arg);
  844.      ch->specials.act = bits;
  845.      if(!IS_SET(ch->specials.act, ACT_SCRIPT))
  846.        SET_BIT(ch->specials.act, ACT_SCRIPT);
  847.      if(!IS_SET(ch->specials.act, ACT_ISNPC))
  848.        SET_BIT(ch->specials.act, ACT_ISNPC);
  849.    }
  850.    ch->commandp++;
  851.    return;
  852.  }
  853.  
  854. void do_jmp(char *arg, struct char_data *ch)
  855. {
  856.  int i;
  857.  char buf[255];
  858.  
  859.  for(i = 0; strcmp(script_data[ch->script].script[i].line, "end\n"); i++) {
  860.     strcpy(buf,script_data[ch->script].script[i].line);
  861.     if(buf[strlen(buf) - 1] == '\n')
  862.        buf[strlen(buf) - 1] = '\0';
  863.  
  864.     if(!strncmp(buf, arg, strlen(arg))) {
  865.        ch->commandp = i;
  866.        return;
  867.      }
  868.   }
  869.  
  870.  sprintf(buf, "Label %s undefined in script assigned to %s.  Ignoring.", arg, GET_NAME(ch));
  871.  log(buf);
  872.  
  873.  ch->commandp++;
  874. }
  875.  
  876. void do_jsr(char *arg, struct char_data *ch)
  877. {
  878.  int i;
  879.  char buf[255];
  880.  
  881.  for(i = 0; strcmp(script_data[ch->script].script[i].line, "end\n"); i++) {
  882.     strcpy(buf,script_data[ch->script].script[i].line);
  883.     if(buf[strlen(buf) - 1] == '\n')
  884.        buf[strlen(buf) - 1] = '\0';
  885.  
  886.     if(!strncmp(buf, arg, strlen(arg))) {
  887.        ch->commandp2 = ch->commandp + 1;
  888.        ch->commandp = i;
  889.        return;
  890.      }
  891.   }
  892.  
  893.  sprintf(buf, "Label %s undefined in script assigned to %s.  Ignoring.", arg, GET_NAME(ch));
  894.  log(buf);
  895.  
  896.  ch->commandp++;
  897. }
  898.  
  899. void do_rts(char *arg, struct char_data *ch)
  900. {
  901.  ch->commandp = ch->commandp2;
  902.  ch->commandp2 = 0;
  903. }
  904.  
  905. void MobHit(struct char_data *ch, struct char_data *v, int type)
  906. {
  907.   int base, percent, learned;
  908.   struct obj_data *o;
  909.  
  910.   if (type != 0) {
  911.     hit(ch,v,type);
  912.   }
  913.  
  914.   /* backstab thing */
  915.   if (ch->equipment[WIELD]) {
  916.     o = ch->equipment[WIELD];
  917.     if (o->obj_flags.value[3] != 11 && o->obj_flags.value[3] != 1 &&
  918.     o->obj_flags.value[3] != 10) {
  919.       hit(ch,v,0);
  920.     } else {
  921.       if (ch->specials.fighting) {
  922.     return;
  923.       }
  924.  
  925.       if (v->specials.fighting) {
  926.     base = 0;
  927.       } else {
  928.     base = 4;
  929.       }
  930.  
  931.       learned = 50 + GetMaxLevel(ch);
  932.       percent = number(1,100);
  933.       if (percent > learned) {
  934.     if (AWAKE(v)) {
  935.       damage(ch, v, 0, SKILL_BACKSTAB);
  936.       AddHated(v, ch);
  937.     } else {
  938.       base += 2;
  939.       GET_HITROLL(ch) += base;
  940.       hit(ch,v,SKILL_BACKSTAB);
  941.       GET_HITROLL(ch) -= base;
  942.       AddHated(v, ch);
  943.     }
  944.       } else {
  945.     GET_HITROLL(ch) += base;
  946.     hit(ch,v,SKILL_BACKSTAB);
  947.     GET_HITROLL(ch) -= base;
  948.     AddHated(v, ch);
  949.       }
  950.     }
  951.   } else {
  952.     hit(ch,v,0);
  953.   }
  954. }
  955.